package org.windowkit.toolkit.widget;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.Timer;

/**
 * This control will make a Component appear to be flashing on and off for a given
 * period of time.
 *
 * @author Rich
 *
 */
public class ComponentFlasher implements ActionListener {

    /** The component that will be flashing. */
    protected JComponent flashee;

    /** The 'off' background color of the component. */
    protected Color initBG;

    /** The 'off' foreground color of the component. */
    protected Color initFG;

    /** The 'on' background color of the component. */
    protected Color flashBGColor;

    /** The 'on' foreground color of the component. */
    protected Color flashFGColor;

    /** Timer object that controls the flashing. */
    protected Timer timer;

    /** The delay between flashing on and off. */
    protected int delay;

    /** Describes the current state of the components flash. */
    protected boolean on;

    /** The current flash count. */
    protected int flashCount;

    /** How many flashes before we stop. */
    protected int maxFlashes;


    public static final int DEFAULT_MAX_FLASHES = 5;
    public static final int DEFAULT_DELAY = 100;

    /**
     * Create a Component Flasher using the default values for
     * delay and flash count.
     *
     * @param toBeFlashed
     */
    public ComponentFlasher(final JComponent toBeFlashed){
        this(toBeFlashed, DEFAULT_DELAY, DEFAULT_MAX_FLASHES);
    }

    /**
     * Create a Component Flasher that will flash the given component.
     *
     * @param toBeFlashed
     *          The Component that will be flashed.
     * @param delay
     *          The amount of time between flashing on and off in ms.
     *          A full flash cycle(on->off) will take 2 * delay long.
     * @param maxFlashes
     *          The number of full flash cycles to do when flashing.
     *          The Component will allways be left in the off state.
     */
    public ComponentFlasher(final JComponent toBeFlashed, final int delay, final int maxFlashes) {
        super();

        flashee = toBeFlashed;
        flashee.setOpaque(true);

        initBG = flashee.getBackground();
        initFG = flashee.getForeground();

        flashBGColor = Color.RED;
        flashFGColor = Color.BLACK;


        setDelay(delay);
        setMaxFlashes(maxFlashes);

    }

    /**
     * Start flashing!
     * If we are allready flashing this will do nothing.
     */
    public void flash(){
        if(timer != null){

            if(timer.isRunning()){
                return;
            }
        }else{
            timer = new Timer(delay, this);
        }
        on = false;
        flashCount = 0;
        timer.start();
    }

    /*
     *  (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(final ActionEvent e) {
        if(e.getSource() == timer){
            if(on){
                on = false;
                flashCount++;
                flashee.setBackground(initBG);
                flashee.setForeground(initFG);
            }else{
                on = true;
                flashee.setBackground(flashBGColor);
                flashee.setForeground(flashFGColor);
            }
            if(flashCount == maxFlashes){
                timer.stop();
            }
        }
    }

    /**
     * Set the delay to use between turning the flash on and off.
     * A full flash will take 2 * delay long.
     *
     * @param delay
     *          The flash delay in ms.
     */
    public void setDelay(final int delay) {
        this.delay = (delay > 0 ? delay : DEFAULT_DELAY);
        if(timer != null){
            timer.setDelay(this.delay);
        }
    }

    /**
     * Set the back ground color to use when the flash is on.
     *
     * @param flashColor
     */
    public void setFlashBGColor(final Color flashColor) {
        this.flashBGColor = flashColor;
    }

    /**
     * Set the number of time this component should flash before it stops.
     * A flash is considered to be one full on/off cycle.
     *
     * @param maxFlashes
     */
    public void setMaxFlashes(final int maxFlashes) {
        this.maxFlashes = (maxFlashes > 0 ? maxFlashes : DEFAULT_MAX_FLASHES);
    }

    /**
     * Set the foreground color to use when flashing.
     *
     * @param flashFGColor
     */
    public void setFlashFGColor(final Color flashFGColor) {
        this.flashFGColor = flashFGColor;
    }

}
